package yxy.game.pm2.module.guard;

import org.joda.time.DateTime;
import org.redisson.api.RSet;
import yxy.apple.util.redisson.RedisException;
import yxy.cherry.data.DataCenter;
import yxy.cherry.data.bean.guarddate;
import yxy.cherry.data.bean.packagedata;
import yxy.cherry.data.function.Function;
import yxy.cherry.data.string.GameString;
import yxy.game.pm2.bean.Currency;
import yxy.game.pm2.bean.area.AreaBean;
import yxy.game.pm2.bean.currency.Currencies;
import yxy.game.pm2.bean.module.AreaModule;
import yxy.game.pm2.bean.module.RedisLock;
import yxy.game.pm2.bean.module.rank.RankEntry;
import yxy.game.pm2.bean.module.rank.RankModule;
import yxy.game.pm2.bean.mq.CCReason;
import yxy.game.pm2.module.mail.MailHandle;
import yxy.game.pm2.module.mail.MailTypeEnum;
import yxy.game.pm2.module.player.FunctionHandle;
import yxy.game.pm2.module.player.RankPlayerPower;

import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.LinkedList;

public class GuardModule extends AreaModule {

	public static enum GuardState {
		GS_0_选将(0), GS_1_守将(1), GS_2_攻城(2), GS_3_守胜(3), GS_4_攻胜(4),;

		private int value;

		private GuardState(int value) {
			this.value = value;
		}

		public int getValue() {
			return value;
		}

		public GuardState getNext() {
			switch (this) {
			case GS_0_选将:
				return GS_1_守将;
			case GS_1_守将:
				return GS_2_攻城;
			case GS_2_攻城:
				return GS_3_守胜;
			default:
				return GS_0_选将;
			}
		}
	}

	// bean===========================================================================

	private LinkedList<Guard> guards = new LinkedList<>();// 守卫信息
	private ArrayList<Long> inspire = new ArrayList<>();// 激励cd时间

	private DateTime startTime;
	private HashMap<GuardState, DateTime> stateTimes = new HashMap<>();
	private GuardState state;

	public LinkedList<Guard> getGuards() {
		return guards;
	}

	public void setGuards(LinkedList<Guard> guards) {
		this.guards = guards;
	}

	public ArrayList<Long> getInspire() {
		return inspire;
	}

	public void setInspire(ArrayList<Long> inspire) {
		this.inspire = inspire;
	}

	public DateTime getStartTime() {
		return startTime;
	}

	public void setStartTime(DateTime startTime) {
		this.startTime = startTime;
	}

	public HashMap<GuardState, DateTime> getStateTimes() {
		return stateTimes;
	}

	public void setStateTimes(HashMap<GuardState, DateTime> stateTimes) {
		this.stateTimes = stateTimes;
	}

	public GuardState getState() {
		return state;
	}

	public void setState(GuardState state) {
		this.state = state;
	}
	// func===========================================================================

	public int current() {
		int index = 0;
		for (Guard guard : getGuards()) {
			if (guard.alive()) {
				return index;
			}
			index++;
		}
		return getGuards().size() - 1;
	}

	public int inspireValue() {
		int inspire = 0;// 激励值
		int add = data().getInspire();// 增加
		long now = DateTime.now().getMillis();
		for (Long time : getInspire()) {
			if (time > now) {
				inspire += add;
			}
		}
		return inspire;
	}

	private void updateInspire(DateTime now) {
		long time = now.getMillis();
		int index = 0;
		for (Long cd : getInspire()) {
			if (cd > time) {
				break;
			}
			index++;
		}
		if (index > 0) {
			setInspire(new ArrayList<>(getInspire().subList(index, getInspire().size())));
		}
	}

	// 袭营
	public void raid(DateTime now) {
		updateInspire(now);
		int n = data().getRaid() / data().getInspire();// 去除层数
		if (getInspire().size() <= n) {
			getInspire().clear();
			return;
		}
		setInspire(new ArrayList<>(getInspire().subList(n, getInspire().size())));
	}

	// 激励
	public void inspire(DateTime now) {
		updateInspire(now);
		getInspire().add(now.plusSeconds(data().getInspirecd()).getMillis());
	}

	public void resetState(DateTime time) {
		DateTime startTime = time.withTimeAtStartOfDay();
		getStateTimes().clear();
		getStateTimes().put(GuardState.GS_0_选将, startTime.plusHours(21));
		getStateTimes().put(GuardState.GS_1_守将, startTime.plusDays(1).plusHours(20).plusMinutes(30));
		getStateTimes().put(GuardState.GS_2_攻城, startTime.plusDays(1).plusHours(21).plusMinutes(30));
		getStateTimes().put(GuardState.GS_3_守胜, startTime.plusDays(3));
		getStateTimes().put(GuardState.GS_4_攻胜, startTime.plusDays(3));

		setState(GuardState.GS_0_选将);

		setStartTime(startTime);
	}

	// XXX TEST 短时测试5分钟
//	public void resetState(DateTime time) {
//		DateTime startTime = time.withTimeAtStartOfDay();
//		if (getStateTimes().containsKey(GuardState.GS_4_攻胜)) {
//			startTime = startTime.plusHours(time.getHourOfDay()).plusMinutes(time.getMinuteOfHour());
//		}
//
//		getStateTimes().clear();
//		getStateTimes().put(GuardState.GS_0_选将, startTime.plusSeconds(15));
//		getStateTimes().put(GuardState.GS_1_守将, startTime.plusSeconds(30));
//		getStateTimes().put(GuardState.GS_2_攻城, startTime.plusMinutes(4).plusSeconds(45));
//		getStateTimes().put(GuardState.GS_3_守胜, startTime.plusMinutes(5));
//		getStateTimes().put(GuardState.GS_4_攻胜, startTime.plusMinutes(5));
//
//		setState(GuardState.GS_0_选将);
//
//		setStartTime(startTime);
//	}

	// XXX TEST 短时测试30分钟
//	public void resetState(DateTime time) {
//		DateTime startTime = time.withTimeAtStartOfDay();
//		if (getStateTimes().containsKey(GuardState.GS_4_攻胜)) {
//			startTime = startTime.plusHours(time.getHourOfDay());
//			if (time.getMinuteOfHour() >= 30) {
//				startTime = startTime.plusMinutes(30);
//			}
//		}
//
//		getStateTimes().clear();
//		getStateTimes().put(GuardState.GS_0_选将, startTime.plusMinutes(3));
//		getStateTimes().put(GuardState.GS_1_守将, startTime.plusMinutes(5));
//		getStateTimes().put(GuardState.GS_2_攻城, startTime.plusMinutes(25));
//		getStateTimes().put(GuardState.GS_3_守胜, startTime.plusMinutes(30));
//		getStateTimes().put(GuardState.GS_4_攻胜, startTime.plusMinutes(30));
//
//		setState(GuardState.GS_0_选将);
//
//		setStartTime(startTime);
//	}

	public void updateState(GuardState state) {
		AreaBean areaBean = AreaBean.get(getAreaId());
		switch (state) {
		case GS_0_选将: {
		}
			break;
		case GS_1_守将: {
			for (int i = 0; i < 3; i++) {
				new RankGuard(areaBean, i).clear();
			}
			clearOffense();
			// 选择战力最高的三个武将作为守将
			getGuards().clear();
			Collection<RankEntry> top = new RankPlayerPower(areaBean).top(3);
			if (top.size() < 3) {
				// 人数过少
				System.err.println("洛阳守卫：人数过少");
				resetState(getStateTimes().get(state).plusDays(1));
				return;
			}

			packagedata data = DataCenter.getData(3003, packagedata.class); // 当选守卫奖励
			Currencies rewards = new Currencies(Currency.create(data.getRewardtype(), data.getRewardid(), data.getRewardnum()));
			for (RankEntry entry : top) {
				String playerCode = entry.getKey();

				Guard guard = Guard.create(playerCode);
				getGuards().addFirst(guard);

				// 邮件发奖
				String title = GameString.守卫洛阳当选守卫奖励_title().getText();
				String content = GameString.守卫洛阳当选守卫奖励_msg().getText();
				new MailHandle().sendMail(entry.getKey(), MailTypeEnum.Mail, title, content, CCReason.洛阳守卫, rewards);
			}
		}
			break;
		case GS_2_攻城:
			break;
		case GS_3_守胜:
			break;
		case GS_4_攻胜:
			break;
		}
		setState(state);
	}

	public boolean guard(String playerCode) {
		for (Guard guard : getGuards()) {
			if (guard.getPlayerCode().equals(playerCode)) {
				return true;
			}
		}
		return false;
	}

	public void update() {

	}

	static private guarddate data;

	static public guarddate data() {
		if (data == null) {
			data = DataCenter.getData(1, guarddate.class);
		}
		return data;
	}


	 public void sendComfortReward(AreaBean areaBean) {
		int current = current();
		//最后还是在0关  发安慰奖
		if(current == 0 ){
			RankModule rank = RankGuard.getRank(areaBean, current);
			Collection<RankEntry> all = rank.all();
			packagedata data = DataCenter.getData(3004, packagedata.class);
			Currencies rewards = new Currencies(Currency.create(data.getRewardtype(), data.getRewardid(), data.getRewardnum()));
			for (RankEntry entry : all) {
				// 邮件发奖
				String title = GameString.守卫洛阳参与奖励_title().getText();
				String content = GameString.守卫洛阳参与奖励_msg().getText();
				new MailHandle().sendMail(entry.getKey(), MailTypeEnum.Mail, title, content, CCReason.洛阳守卫, rewards);
			}

		}
	}





	// redis==========================================================================

	static private String key(int areaId) {
		return key(areaId, "GUARD");
	}

	public void set() {
		try {
			setv(key(getAreaId()), this);
		} catch (RedisException e) {
			e.printStackTrace();
		}
	}

	public static GuardModule get(String playerCode) {
		AreaBean area = area(playerCode);
		return get(area.getAreaId());
	}

	public static GuardModule get(int areaId) {
		try {
			GuardModule module = getv(key(areaId));

			if (module == null) {
				module = create(areaId);
			}
			module.update();
			return module;
		} catch (RedisException e) {
			e.printStackTrace();
		}
		return null;
	}

	private static GuardModule create(int areaId) {
		GuardModule module = new GuardModule();
		module.setAreaId(areaId);
		module.resetState(DateTime.now());

		module.set();
		return module;
	}

	private static RSet<String> offenseSet(int areaId) {
		return redis().client().getSet(String.format("AREA:%s:MODULE:GUARDOFFENSE", areaId));
	}

	public void addOffense(String playerCode) {
		offenseSet(getAreaId()).add(playerCode);
	}

	public boolean isOffense(String playerCode) {
		return offenseSet(getAreaId()).contains(playerCode);
	}

	public void clearOffense() {
		offenseSet(getAreaId()).clear();
	}

	// lock==========================================================================

	@Override
	public String lockKey() {
		return String.format("lock:%s", key(getAreaId()));
	}

	public static RedisLock lock(int areaId) {
		return getLock(String.format("lock:%s", key(areaId)));
	}

}
